﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core;
using Cofe.Core.Filter;
using Cofe.Core.Implements;
using Cofe.Core.Property;

namespace Cofe.Data
{
    /// <summary>
    /// Update / Read database, require dispose().
    /// </summary>
    public interface IRepository : IDisposable
    {
        /// <summary>
        /// Add one or more entry to database.
        /// </summary>
        /// <param name="forceUpdate"></param>
        /// <param name="isDirectoryUpdate">Assume all Phs propertyHosts share the same propertyHost, 
        /// remove if other entries in first ph's parent but not in propertyHosts parameter.</param>
        /// <param name="propertyHosts"></param>
        DatabaseEntry[] AddOrUpdate(bool forceUpdate, bool isDirectoryUpdate, params IPropertyHost[] propertyHosts);

        /// <summary>
        /// Add subcontent to database.
        /// </summary>
        /// <param name="parentPropertyHost"></param>
        /// <returns></returns>
        DatabaseEntry[] RefreshListing(IPropertyHost parentPropertyHost);
        
        void ChangeValue<T>(DatabaseEntry dbEntry, Expression<Func<DatabaseEntry, T>> propertySelector, T value);
        //void SetValue<T>(DatabaseEntry dbEntry, Expression<Func<CofeSystemInfo, T>> propertySelector, T value);
        T GetValue<T>(DatabaseEntry dbEntry, Expression<Func<CofeSystemInfo, T>> propertySelector);

        bool Exists(FilterCollections filters);

        /// <summary>
        /// Remove entries that match the query.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="query"></param>
        void Remove(FilterCollections filters);

        
        void Remove(string parseName);
        void Remove(Guid id);

        void Expire(FilterCollections filters);

        void Expire(Guid id);

        void Refresh(FilterCollections filters, bool refreshCacheTime = true, bool refreshListTime = true);
        void Refresh(Guid id, bool refreshCacheTime = true, bool refreshListTime = true);

        int ModifyHashTag(FilterCollections filters, string[] addTag, string[] removeTag);

        IEnumerable<DatabaseEntry> FindDbEntry(FilterCollections filters);     

        /// <summary>
        /// Find a DatabaseEntry using the expression.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        IEnumerable<IPropertyHost> FindAll(FilterCollections filters);

        IEnumerable<DatabaseUpdateEntry> FindExpired(UpdateType updateType, int count);

        int Count(FilterCollections filters);     

        /// <summary>
        /// Find a ICofeSystemInfo of specified type using the expression.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        IEnumerable<T> FindAll<T>(FilterCollections filters) where T : ICofeSystemInfo;

        void SaveChanges();

        IDatabaseEntryFactory DatabaseEntryFactory { get; }

        IEventRepository EventRepository { get; }
    }
}
